#ifndef __I264E_OSDEP_H__
#define __X264E_OSDEP_H__

#include <stdint.h>
#include <math.h>
#include <pthread.h>

#ifndef CONFIG_HAVE_LOG2F
#define log2f(x) (logf(x)/0.693147180559945f)
#define log2(x) (log(x)/0.693147180559945)
#endif

#define DECLARE_ALIGNED(var, n) var __attribute__((aligned(n)))
#define ALIGNED_32(var) DECLARE_ALIGNED( var, 32 )
#define ALIGNED_16(var) DECLARE_ALIGNED( var, 16 )
#define ALIGNED_8(var)  DECLARE_ALIGNED( var, 8 )
#define ALIGNED_4(var)  DECLARE_ALIGNED( var, 4 )

#define ALIGNED_ARRAY_EMU( mask, type, name, sub1, ... )\
    uint8_t name##_u [sizeof(type sub1 __VA_ARGS__) + mask]; \
    type (*name) __VA_ARGS__ = (void*)((intptr_t)(name##_u+mask) & ~mask)

#define ALIGNED_ARRAY_8( type, name, sub1, ... )\
    ALIGNED_8( type name sub1 __VA_ARGS__ )

#define ALIGNED_ARRAY_16( type, name, sub1, ... )\
    ALIGNED_16( type name sub1 __VA_ARGS__ )

#define EXPAND(x) x

#if STACK_ALIGNMENT >= 32
#define ALIGNED_ARRAY_32( type, name, sub1, ... )\
    ALIGNED_32( type name sub1 __VA_ARGS__ )
#else
#define ALIGNED_ARRAY_32( ... ) EXPAND( ALIGNED_ARRAY_EMU( 31, __VA_ARGS__ ) )
#endif

#define ALIGNED_ARRAY_64( ... ) EXPAND( ALIGNED_ARRAY_EMU( 63, __VA_ARGS__ ) )

#define NATIVE_ALIGN	32
#define ALIGNED_N ALIGNED_32
#define ALIGNED_ARRAY_N ALIGNED_ARRAY_32

#define UNINIT(x) x=x

#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
#define UNUSED __attribute__((unused))
#define ALWAYS_INLINE __attribute__((always_inline)) inline
#define NOINLINE __attribute__((noinline))
#define MAY_ALIAS __attribute__((may_alias))
#else
#define ALWAYS_INLINE inline
#define NOINLINE
#define UNUSED
#define MAY_ALIAS
#endif

#define i264e_pthread_t               pthread_t
#define i264e_pthread_create          pthread_create
#define i264e_pthread_join            pthread_join
#define i264e_pthread_mutex_t         pthread_mutex_t
#define i264e_pthread_mutex_init      pthread_mutex_init
#define i264e_pthread_mutex_destroy   pthread_mutex_destroy
#define i264e_pthread_mutex_lock      pthread_mutex_lock
#define i264e_pthread_mutex_unlock    pthread_mutex_unlock
#define i264e_pthread_cond_t          pthread_cond_t
#define i264e_pthread_cond_init       pthread_cond_init
#define i264e_pthread_cond_destroy    pthread_cond_destroy
#define i264e_pthread_cond_broadcast  pthread_cond_broadcast
#define i264e_pthread_cond_wait       pthread_cond_wait
#define i264e_pthread_attr_t          pthread_attr_t
#define i264e_pthread_attr_init       pthread_attr_init
#define i264e_pthread_attr_destroy    pthread_attr_destroy
#define i264e_pthread_num_processors_np pthread_num_processors_np
#define X264_PTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER

#define WORD_SIZE sizeof(void*)

extern inline uint32_t endian_fix32( uint32_t x );
extern inline uint64_t endian_fix64( uint64_t x );
extern inline intptr_t endian_fix( intptr_t x );
extern inline uint16_t endian_fix16( uint16_t x );
/* For values with 4 bits or less. */
extern int inline i264e_ctz_4bit( uint32_t x );
#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 3)
#define i264e_clz(x) __builtin_clz(x)
#define i264e_ctz(x) __builtin_ctz(x)
#else
extern int inline i264e_clz( uint32_t x );
extern int inline i264e_ctz( uint32_t x );
#endif
#endif /* __I264E_OSDEP_H__ */
